﻿using System.Reflection;
using rpc_service.cache;
using Microsoft.CodeAnalysis;

namespace rpc_service.core.support.assembly.roslyn;

public class RoslynReferences
{
    public List<MetadataReference> GenerateReferences() {
        var references = new List<MetadataReference>
        {
            MetadataReference.CreateFromFile("object".GetType().Assembly.Location),
            MetadataReference.CreateFromFile("Console".GetType().Assembly.Location)
        };
        
        addRuntimeReferences(references);
        addSystemReferences(references);
        addCurrentAssemblyReference(references);
        addLoadedAssembliesReferences(references);
        addSpecialReferences(references);

        return references;
    }

    /// <summary>
    /// 添加运行时基础引用
    /// </summary>
    /// <param name="references">引用集合</param>
    private void addRuntimeReferences(List<MetadataReference> references)
    {
        // 获取运行时路径
        string runtimePath = Path.GetDirectoryName("object".GetTypeByStr().Assembly.Location);
        
        // 添加基础运行时组件
        references.Add(MetadataReference.CreateFromFile(Path.Combine(runtimePath, "System.Runtime.dll")));
        references.Add(MetadataReference.CreateFromFile(Path.Combine(runtimePath, "System.Threading.Tasks.dll")));
    }
    
    /// <summary>
    /// 添加系统功能引用
    /// </summary>
    /// <param name="references">引用集合</param>
    private void addSystemReferences(List<MetadataReference> references)
    {
        // 获取运行时路径
        string runtimePath = Path.GetDirectoryName("object".GetTypeByStr().Assembly.Location)!;
        
        // 添加网络和数据处理相关引用
        references.Add(MetadataReference.CreateFromFile(Path.Combine(runtimePath, "System.Net.Http.dll")));
        references.Add(MetadataReference.CreateFromFile(Path.Combine(runtimePath, "System.Linq.dll")));
        references.Add(MetadataReference.CreateFromFile(Path.Combine(runtimePath, "System.Text.Json.dll")));
        references.Add(MetadataReference.CreateFromFile("Uri".GetTypeByStr().Assembly.Location));
    }
    
    /// <summary>
    /// 添加当前程序集引用
    /// </summary>
    /// <param name="references">引用集合</param>
    private void addCurrentAssemblyReference(List<MetadataReference> references)
    {
        // 添加当前执行程序集的引用
        references.Add(MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location));
    }
    
    /// <summary>
    /// 添加所有已加载程序集的引用
    /// </summary>
    /// <param name="references">引用集合</param>
    private void addLoadedAssembliesReferences(List<MetadataReference> references)
    {
        // 遍历当前应用程序域中所有已加载的程序集
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            try
            {
                // 只添加非动态程序集且有有效位置的程序集
                if (!assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location))
                {
                    references.Add(MetadataReference.CreateFromFile(assembly.Location));
                }
            }
            catch (Exception ex)
            {
                // 记录添加引用时的错误
                Console.WriteLine($"添加程序集引用时出错: {ex.Message}");
            }
        }
    }
    
    /// <summary>
    /// 添加特殊引用
    /// </summary>
    /// <param name="references">引用集合</param>
    private void addSpecialReferences(List<MetadataReference> references)
    {
        try
        {
            // 获取运行时路径
            string runtimePath = Path.GetDirectoryName("object".GetTypeByStr().Assembly.Location)!;
            
            // 添加 System.Private.Uri 引用（如果存在）
            string uriPath = Path.Combine(runtimePath, "System.Private.Uri.dll");
            if (File.Exists(uriPath))
            {
                references.Add(MetadataReference.CreateFromFile(uriPath));
            }
        }
        catch (Exception ex)
        {
            // 记录添加特殊引用时的错误
            Console.WriteLine($"添加 System.Private.Uri 引用时出错: {ex.Message}");
        }
    }
}